#include <iostream>

using namespace std;

void recoup(int) noexcept;          // 不会抛出异常
void recoup(int) throw();           // 不会抛出异常
void recoup(int) noexcept(true);    // 不会抛出异常
void alloc(int);                    // 可能抛出异常
void alloc(int) noexcept(false);    // 可能抛出异常

// 如果函数 g 承诺了不会抛出异常，则 f 也不会抛出异常
// 如果函数 g 未承诺，则 f 也可能抛出异常
// void f() noexcept(noexcept(g()));

/**
 * 违反了异常说明，但仍可以顺利编译通过
 * 一旦抛出了异常，程序就会调用 terminate 函数
 */
void f() noexcept
{
    throw exception();
}

class Base {
    public:
        virtual double f1(double) noexcept;
        virtual int f2() noexcept(false);
        virtual void f3();
};

class Derived : public Base {
    public:
        // double f1(double);       // 错误：虚函数 f1 承诺不会抛出异常
        int f2() noexcept(false);   // 正确：异常说明一致
        void f3() noexcept;         // 正确：对抛出异常做了更严格的限定
};

int main()
{
    // recoup 抛异常返回 true，否则返回 false
    noexcept(recoup(0));

    // recoup 和 pf1 都承诺不会抛出异常
    void (*pf1)(int) noexcept = recoup;
    // 正确：recoup 不会抛出异常，pf2 可能抛出异常，二者之间互不干扰
    void (*pf2)(int) = recoup;

    // pf1 = alloc;     // 错误：alloc 可能抛出异常，但是 pf1 承诺不会抛出异常
    pf2 = alloc;        // 正确：pf2 和 alloc 都可能抛出异常
}